package com.zhuangjie.mvc.ws.core;

import com.alibaba.nacos.common.packagescan.resource.AntPathMatcher;
import com.zhaungjie.base.utils.ReflectionUtils;
import com.zhuangjie.mvc.ws.Interceptor.WebSocketInterceptor;
import com.zhuangjie.mvc.ws.annotation.WSInterceptor;
import com.zhuangjie.mvc.ws.utils.ContextPathHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketSession;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class WebSocketInterceptorStore {
    private Map<String, WebSocketInterceptor> interceptorMap = new HashMap<>();

    @Autowired(required = false)
    private List<WebSocketInterceptor> interceptors;

    @Autowired
    private ContextPathHelper contextPathHelper;

    /**
     * 收集配置的拦截器
     */
    @PostConstruct
    private void init() {
        if (interceptors == null) return;
        for (WebSocketInterceptor interceptor : interceptors) {
            WSInterceptor wsInterceptor = ReflectionUtils.getAnnotationFromInstance(interceptor, WSInterceptor.class);
            if (wsInterceptor == null) {
                continue;
            }
            interceptorMap.put(contextPathHelper.fullRequestRootPath(wsInterceptor.rule()), interceptor);
        }
    }

    /**
     * 获取拦截器
     *
     * @param session 一场
     * @return {@link WebSocketInterceptor}
     */
    public WebSocketInterceptor getInterceptor(WebSocketSession session) {
        if (this.interceptorMap == null) {
            return null;
        }
        String fullRootPath = session.getUri().getPath();
        AntPathMatcher antPathMatcher = new AntPathMatcher();
        for (Map.Entry<String, WebSocketInterceptor> entry : this.interceptorMap.entrySet()) {
            String pathRule = entry.getKey();
            if (antPathMatcher.match(pathRule, fullRootPath)) {
                // 只要有一个匹配就不往下找了，也就是如果出现拦截咕咕重叠只有一个生效
                return entry.getValue();
            }
        }
        return null;
    }
}
